home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
QRZ! Ham Radio 8
/
QRZ Ham Radio Callsign Database - Volume 8.iso
/
pc
/
files
/
t_unix
/
j109lxa4.tar
/
sessmgr.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-06-04
|
25KB
|
1,111 lines
/*
* Session manager and session manager switch
*
* The session manager switch intercepts all session and console I/O calls and
* forwards them to session managers based on the switch entry managing the
* session, or the system default session manager for new sessions. New
* sessions may also be started attached to specific session managers.
* Sessions can also be "reparented" from one session manager to another.
*
* Per-session options are now supported. Per-session-*manager* options have
* assigned slots in the session manager definition, but are not yet supported.
*/
#include "global.h"
#include "hardware.h"
#include "proc.h"
#include "socket.h"
#undef tputs
#include "tty.h"
#include "sessmgr.h"
#include "cmdparse.h"
#include "commands.h"
#include "config.h"
static int dosmstatus __ARGS((int, char **, void *));
static int dosmdefault __ARGS((int, char **, void *));
static int dosmcreate __ARGS((int, char **, void *));
static int dosmreparent __ARGS((int, char **, void *));
static int dosmoptions __ARGS((int, char **, void *));
/*
* The session manager switch: an array of pointers to session managers.
*/
#ifdef SM_CURSES
extern struct sessmgr_sw curses_sessmgr;
#endif
#ifdef SM_RAW
extern struct sessmgr_sw raw_sessmgr;
#endif
#ifdef SM_DUMB
extern struct sessmgr_sw dumb_sessmgr;
#endif
static struct sessmgr_sw *sessmgr_sw[] =
{
#ifdef SM_CURSES
&curses_sessmgr,
#endif
#ifdef SM_DUMB
&dumb_sessmgr,
#endif
#ifdef SM_RAW
&raw_sessmgr,
#endif
0,
};
static int sesm_initted;
/*
* Commands for session manager administration
*/
static struct cmds SMcmds[] =
{
"create", dosmcreate, 0, 0, NULLCHAR,
"default", dosmdefault, 0, 0, NULLCHAR,
"options", dosmoptions, 0, 0, NULLCHAR,
"reparent", dosmreparent, 0, 0, NULLCHAR,
"status", dosmstatus, 0, 0, NULLCHAR,
NULLCHAR, NULLFP((int,char**,void*)), 0, 0, NULLCHAR,
};
static struct cmds SMsessions[] =
{
#ifdef MAILBOX
"bbs", dobbs, 1024, 0, NULLCHAR,
#endif
#ifdef AX25
#ifdef ALLSESSIONS
"connect", doconnect, 1024, 3,
"connect <interface> <callsign>",
#endif
#endif
#ifdef ALLCMD
"dir", dodir, 0, 0, NULLCHAR,
#endif
#ifdef DIALER
"dialer", dodialer, 512, 2,
"dialer <iface> [<file> [<seconds> [<pings> [<hostid>]]]]",
#endif
#ifdef ALLCMD
"finger", dofinger, 1024, 2, "finger name[@host]",
#endif
#ifdef ALLSESSIONS
"ftp", doftp, 2048, 2, "ftp <address>",
#endif
#ifdef HOPCHECK
/* hopcheck - need to restrict to hopcheck itself */
#endif
#ifdef ALLCMD
"more", domore, 0, 2, "more <file> [searchstring]",
#endif
#ifdef NETROM
/* netrom connect */
#endif
"ping", doping, 512, 4,
"ping <hostid> <length> <interval> [incflag]",
#ifdef RLOGINCLI
"rlogin", dorlogin, 2048, 2, "rlogin <address>",
#endif
#ifdef AX25
#ifdef ALLSESSIONS
#ifdef ALLSERV
"split", doconnect, 1024, 3,
"split <interface> <callsign>",
#endif
#endif
#endif
#ifdef ALLSESSIONS
"telnet", dotelnet, 1024, 2, "telnet <address> [port]",
#endif
#ifdef ALLSERV
"ttylink", dotelnet, 1024, 2, "ttylink <address> [port]",
#endif
NULLCHAR, NULLFP((int,char**,void*)), 0, 0, NULLCHAR,
};
/*
* Used by the newscreen() entry point, the creation of the trace session
* in main(), and by reparenting.
*/
static void
sm_newscreen(char *sc, struct session *sp)
{
struct sessmgr_sw *sm;
char *cp;
if (!(sm = sm_lookup(sc, &cp)))
{
sm = sessmgr_sw[0]; /* system-wide default session manager */
cp = 0;
}
if (!sp)
return;
sp->screen = mallocw(sizeof *sp->screen);
if (!(sm->flags & SM_INIT))
{
if (Current && Current != sp && Current->screen &&
!(Current->screen->sessmgr->flags & SM_SUSPEND))
{
(*Current->screen->sessmgr->suspend)(Current->screen->sessmgr);
Current->screen->sessmgr->flags |= SM_SUSPEND;
}
(*sm->init)(sm);
sm->flags |= SM_INIT;
}
sm->refcnt++;
sp->screen->sessmgr = sm;
sp->screen->sesmdat =
(*sm->create)(sm, sp);
if (sm->sessopt && cp)
(*sm->sessopt)(sm, sp->screen->sesmdat, cp);
sp->screen->flags = 0;
if (sp->split)
sp->screen->flags |= SMS_SPLIT;
if (!(sm->flags & SM_SPLIT))
sp->split = 0; /* if sm can't do split, split sessions are deranged */
sp->screen->next_sm = strdup(sc);
sp->screen->use_sm = sp->screen->next_sm;
if (sm->flags & SM_SUSPEND)
{
(*Current->screen->sessmgr->resume)(Current->screen->sessmgr);
Current->screen->sessmgr->flags &= ~SM_SUSPEND;
}
#if 0
/* this is ugly... */
/* (it's also wrong; figure it out later...) */
if (sp->type == TRACESESSION)
sp->screen->flags |= SMS_DISCARD;
#endif
}
int
dosessmgr(int argc, char **argv, void *p)
{
if (argc < 2)
return dosmstatus(argc, argv, p);
return subcmd(SMcmds, argc, argv, p);
}
int
dosmstatus(int argc, char **argv, void *p)
{
struct screen *sp;
char *cp;
int s;
tprintf("Known session managers are:\n");
for (s = 0; sessmgr_sw[s]; s++)
tprintf("%s\n", sessmgr_sw[s]->name);
tprintf("\n");
dosmdefault(0, 0, 0);
tprintf("\n# Type Name Process Manager Options\n");
tprintf("== ============ ============ ============ ======== ==========\n");
for (s = 0; s < Nsessions; s++)
{
if (Sessions[s].type == FREE)
continue;
tprintf("%-2d %-12s ", s, Sestypes[Sessions[s].type]);
if (Sessions[s].name)
tprintf("%-12.12s ", Sessions[s].name);
else
tprintf(" ");
if (Sessions[s].proc->name && *Sessions[s].proc->name)
tprintf("%-12.12s", Sessions[s].proc->name);
else
tprintf("%8.8lx ", FP_SEG(Sessions[s].proc));
tprintf(" %-8.8s", Sessions[s].screen->sessmgr->name);
/* we don't support session MANAGER options just yet... */
if ((sp = Sessions[s].screen)->sessmgr->sessopt &&
(cp = (*sp->sessmgr->sessopt)(sp->sessmgr, sp->sesmdat,(char *)0)))
tprintf(" %s", cp);
tprintf("\n");
}
return 0;
}
int
dosmdefault(int argc, char **argv, void *p)
{
char *cp;
if (argc < 2)
{
if (Current && Current->screen && Current->type == COMMAND)
cp = Current->screen->next_sm;
else if (Command && Command->screen)
cp = Command->screen->next_sm;
else
cp = "";
if (!cp || !*cp)
cp = sessmgr_sw[0]->name;
tprintf("Session manager for new sessions is \"%s\".\n", cp);
return 0;
}
if (argc > 2)
{
tprintf("usage: sessmgr default [session-manager]\n");
return 1;
}
if (!sm_lookup(argv[1], 0))
{
tprintf("No such session manager: \"%s\"\n", argv[1]);
return 1;
}
if (Current->screen->next_sm)
free(Current->screen->next_sm);
Current->screen->next_sm = strdup(argv[1]);
return 0;
}
int
dosmcreate(int argc, char **argv, void *p)
{
int rc;
if (argc < 3)
{
tprintf("usage: sessmgr create session-manager command [args...]\n");
return 1;
}
if (!sm_lookup(argv[1], 0))
{
tprintf("Unknown session manager \"%s\"\n", argv[1]);
return 1;
}
if (Current->type != COMMAND)
write(2, "WHOA! I'm not being run from a COMMAND session!\n", 48);
Current->screen->use_sm = argv[1];
rc = subcmd(SMsessions, argc - 1, argv + 1, p);
return rc;
}
int
dosmoptions(int argc, char **argv, void *p)
{
struct screen *sp;
char *cp;
int i;
if (argc < 2)
{
tprintf("usage: sessmgr options session [options]\n");
return 1;
}
if ((i = atoi(argv[1])) < 0 || i > Nsessions || Sessions[i].type == FREE)
{
tprintf("Invalid session %s\n", argv[1]);
return 1;
}
sp = Sessions[i].screen;
if (argc < 3)
{
tprintf("Options for session: ");
if (!sp->sessmgr->sessopt)
cp = 0;
else
cp = (*sp->sessmgr->sessopt)(sp->sessmgr, sp->sesmdat, (char *) 0);
if (!cp)
cp = "(none)";
tprintf("%s\n", cp);
return 0;
}
if (sp->sessmgr->sessopt)
(*sp->sessmgr->sessopt)(sp->sessmgr, sp, argv[2]);
return 0;
}
/*
* Administration of the session manager interface
*/
struct sessmgr_sw *
sm_lookup(char *smname, char **optp)
{
static char buf[1024];
char *cp;
int i;
if (!smname)
{
/* inherit a reasonable session manager */
if (Current && Current->screen && Current->type == COMMAND)
{
smname = Current->screen->use_sm;
Current->screen->use_sm = Current->screen->next_sm;
}
else if (Command && Command->screen)
smname = Command->screen->next_sm;
else
smname = "";
}
i = 0;
for (cp = smname; *cp && *cp != ':'; cp++)
buf[i++] = *cp;
buf[i] = '\0';
if (*cp)
cp++;
else
cp = 0;
if (!i)
{
if (optp) /* is this wise? sessmgr ":opt", that is */
*optp = cp;
return sessmgr_sw[0];
}
for (i = 0; sessmgr_sw[i]; i++)
{
if (strcasecmp(sessmgr_sw[i]->name, buf) == 0)
{
if (optp)
*optp = cp;
return sessmgr_sw[i];
}
}
if (optp)
*optp = 0;
return 0;
}
int
sm_blocked(struct session *sp)
{
/* Return TRUE if the session is blocked. */
return !(sp->screen->flags & SMS_ACTIVE) ||
(sp->screen->sessmgr->flags & SM_SUSPEND);
}
/*
* Session reparenting. This is mildly interesting.
*
* The idea is that a session can be destroyed and recreated. (Actually, the
* session is retained; the screen is destroyed.) The only fly in the oint-
* ment is that you can't retain the contents of the screen: some session
* managers have no backing store ("dumb", and especially "none").
*
* Sessions can be reparented individually or by session manager. Individual
* sessions can be named if they have names.
*/
static void
sm_reparent(struct session *sp, char *new)
{
struct sessmgr_sw *old, *np;
int susp;
if (!(np = sm_lookup(new, 0)))
return;
if ((old = sp->screen->sessmgr) == np)
return;
if (sp->screen->flags & SMS_SPLIT) /* sp->split is 0 if s.m. won't split */
sp->split = 1; /* newscreen will deactivate if needed */
susp = (old->flags & SM_STDIO) && (np->flags & SM_STDIO);
freescreen(sp);
if (susp && !(old->flags & SM_SUSPEND))
{
(*old->suspend)(old);
old->flags |= SM_SUSPEND;
}
sm_newscreen(new, sp);
}
int
dosmreparent(int argc, char **argv, void *p)
{
struct sessmgr_sw *old;
struct session *s;
int i, susp;
if (argc != 3)
{
tprintf("usage: sessmgr reparent <session> <session-manager>\n");
return 1;
}
if (!sm_lookup(argv[2], 0))
{
tprintf("Unknown session manager \"%s\"\n", argv[2]);
return -1;
}
if (isdigit(argv[1][0]))
{
if ((i = atoi(argv[1])) >= Nsessions || Sessions[i].type == FREE)
{
tprintf("Invalid session number %d.\n", i);
return 1;
}
sm_reparent(Sessions + i, argv[2]);
if (Sessions + i == Current)
Sessions[i].screen->flags |= SMS_ACTIVE;
else
{
/* we must do this because newscreen() partially switches us */
swapscreen(Current, Sessions + i);
swapscreen(Sessions + i, Current);
}
return 0;
}
susp = -1;
for (i = 0; i < Nsessions; i++)
{
if (Sessions[i].type == FREE)
continue;
if (Sessions[i].name && *Sessions[i].name &&
strcasecmp(Sessions[i].name, argv[1]) == 0)
{
if (susp != -1)
break;
susp = i;
}
if (Sessions[i].proc->name && *Sessions[i].proc->name &&
strcasecmp(Sessions[i].proc->name, argv[1]) == 0)
{
if (susp != -1)
break;
susp = i;
}
if (strcasecmp(Sestypes[Sessions[i].type], argv[1]) == 0)
{
if (susp != -1)
break;
susp = i;
}
}
if (i != Nsessions)
{
tprintf("Session ID \"%s\" is not unique\n", argv[1]);
return 1;
}
if (susp != -1)
{
sm_reparent(Sessions + susp, argv[2]);
if (Sessions + susp == Current)
Sessions[susp].screen->flags |= SMS_ACTIVE;
else
{
/* we must do this because newscreen() partially switches us */
swapscreen(Current, Sessions + susp);
swapscreen(Sessions + susp, Current);
}
return 0;
}
for (i = 0; sessmgr_sw[i]; i++)
{
if (sessmgr_sw[i]->refcnt &&
strcasecmp(sessmgr_sw[i]->name, argv[1]) == 0)
break;
}
if (!sessmgr_sw[i])
{
tprintf("Can't decipher session ID \"%s\"\n", argv[1]);
return 1;
}
/* reparent all of them! */
old = sessmgr_sw[i];
s = Current;
for (i = 0; i < Nsessions; i++)
{
if (Sessions[i].screen->sessmgr != old)
continue;
sm_reparent(Sessions + i, argv[2]);
swapscreen(s, Sessions + i);
s = Sessions + i;
}
if (s == Current)
Sessions[i].screen->flags |= SMS_ACTIVE;
else
swapscreen(s, Current);
return 0;
}
/*
* Ugly hack for doshell(): tell if the current session manager is SM_STDIO.
*/
int
sm_usestdio(void)
{
return Current->screen->sessmgr->flags & SM_STDIO;
}
/*
* Start a session with a specified session manager. This could be static
* since it's normally only used by the "sessmgr <sm> create" command, but
* we also need it to start the trace session in a different session manager
* from the default.
*
* This incorporates newsession(). Ultimately, newsession() should be changed
* to call this function.
*/
struct session *
sm_newsession(char *sc, char *name, int type, int split)
{
extern int Numrows;
struct session *sp;
int i;
if (!sc || !*sc)
{
/*
* HACK - new sessions should inherit the current session if it is a
* COMMAND session. Else use Command's next session, unless Command
* doesn't exist yet (creation of Command or Trace) in which case the
* default session manager is used.
*
* Maybe this isn't really a hack... but it feels like one.
*/
if (Current && Current->screen && Current->type == COMMAND)
sc = Current->screen->next_sm;
else if (Command && Command->screen)
sc = Command->screen->next_sm;
else
sc = "";
}
if (type == TRACESESSION)
i = Nsessions - 1;
else
{
for (i = 0; i < Nsessions; i++)
{
if (Sessions[i].type == FREE)
break;
}
}
if (i == Nsessions)
return NULLSESSION;
sp = Sessions + i;
sp->type = type;
sp->s = -1;
if (name != NULLCHAR)
sp->name = strdup(name);
sp->proc = Curproc;
/* update Curproc's session pointer as well! */
/* (in theory this could leave a dangling session...?) */
Curproc->session = sp;
/* Create standard input and output sockets. Output is
* translated to local end-of-line by default
*/
Curproc->input = sp->input = socket(AF_LOCAL, SOCK_STREAM, 0);
seteol(Curproc->input, Eol);
sockmode(Curproc->input, SOCK_BINARY);
Curproc->output = sp->output = socket(AF_LOCAL, SOCK_STREAM, 0);
seteol(Curproc->output, Eol);
sockmode(Curproc->output, SOCK_ASCII);
/* on by default */
sp->ttystate.crnl = sp->ttystate.edit = sp->ttystate.echo = 1;
sp->flowmode = 0; /* Off by default */
sp->row = Numrows;
sp->morewait = 0;
sp->split = split;
sm_newscreen(sc, sp);
swapscreen(Current, sp);
Current = sp;
return sp;
}
/*
* Session manager initiation and cleanup.
*/
void
ioinit(int no_itimer)
{
init_sys(no_itimer);
sesm_initted = 1;
}
void
iostop(void)
{
int c;
sesm_initted = 0;
for (c = 0; sessmgr_sw[c]; c++)
{
if (sessmgr_sw[c]->flags & SM_INIT)
(*sessmgr_sw[c]->end)(sessmgr_sw[c]);
}
deinit_sys();
}
/*
* Suspend and resume now only suspend/resume the current session manager.
* It is assumed that the session manger is SM_STDIO and that an outside
* process needs to intercept the SM_STDIO interface temporarily.
*/
void
iosuspend(void)
{
register struct screen *sp = Current->screen;
if ((sp->sessmgr->flags & (SM_INIT|SM_SUSPEND)) == SM_INIT)
{
(*sp->sessmgr->suspend)(sp->sessmgr);
sp->sessmgr->flags |= SM_SUSPEND;
}
}
void
ioresume(void)
{
register struct screen *sp = Current->screen;
if ((sp->sessmgr->flags & (SM_INIT|SM_SUSPEND)) == (SM_INIT|SM_SUSPEND))
{
(*sp->sessmgr->resume)(sp->sessmgr);
sp->sessmgr->flags &= ~SM_SUSPEND;
}
}
/*
* Session creation, destruction, and swapping.
*/
void
j_newscreen(struct session *sp)
{
char *sc;
if (Current && Current->screen && Current->type == COMMAND)
{
sc = Current->screen->use_sm;
Current->screen->use_sm = Current->screen->next_sm;
}
else if (Command && Command->screen)
sc = Command->screen->next_sm;
else
sc = "";
sm_newscreen(sc, sp);
}
void
freescreen(struct session *sp)
{
if (!sp || !sp->screen)
return;
(*sp->screen->sessmgr->destroy)(sp->screen->sessmgr, sp->screen->sesmdat);
free(sp->screen->next_sm);
if (!--sp->screen->sessmgr->refcnt)
{
(*sp->screen->sessmgr->end)(sp->screen->sessmgr);
sp->screen->sessmgr->flags &= ~SM_INIT;
}
free(sp->screen);
sp->screen = 0;
}
void
swapscreen(struct session *old, struct session *new)
{
if (old == new)
return;
/*
* If they're in different session managers, swap each to/from NULL.
* Otherwise, swap them in the common session manager.
*/
if (old && new && old->screen->sessmgr == new->screen->sessmgr)
{
if (!(*old->screen->sessmgr->swtch)(old->screen->sessmgr,
old->screen->sesmdat,
new->screen->sesmdat))
old->screen->flags &= ~SMS_ACTIVE;
}
else
{
if (old)
{
(*old->screen->sessmgr->swtch)(old->screen->sessmgr,
old->screen->sesmdat, 0);
}
if (old && new && (old->screen->sessmgr->flags & SM_STDIO) &&
(new->screen->sessmgr->flags & SM_STDIO) &&
!(old->screen->sessmgr->flags & SM_SUSPEND))
{
(*old->screen->sessmgr->suspend)(old->screen->sessmgr);
old->screen->sessmgr->flags |= SM_SUSPEND;
}
if (new &&
((new->screen->sessmgr->flags & (SM_SUSPEND|SM_STDIO|SM_INIT)) ==
(SM_SUSPEND|SM_STDIO|SM_INIT)))
{
(*new->screen->sessmgr->resume)(new->screen->sessmgr);
new->screen->sessmgr->flags &= ~SM_SUSPEND;
}
if (new)
{
(*new->screen->sessmgr->swtch)(new->screen->sessmgr, 0,
new->screen->sesmdat);
}
}
if (new)
{
new->screen->flags |= SMS_ACTIVE;
j_psignal(new->screen, 0);
}
}
/*
* Some session managers (e.g. curses) aren't re-entrant. We deal with this
* by locking individual screens. (we assume the session manager is reentrant
* between separate screens; this may be unsafe...)
*/
static int
#ifdef __STDC__
LOCKSCR(register struct screen *sc, int wait)
#else
LOCKSCR(sc, wait)
register struct screen *sc;
int wait;
#endif
{
sigset_t s, t;
sigfillset(&s);
sigprocmask(SIG_BLOCK, &s, &t);
while (sc->flags & SM_LOCK)
{
if (!wait)
return 0;
pwait(&sc->flags);
}
sc->flags |= SM_LOCK;
sigprocmask(SIG_SETMASK, &t, 0);
return 1;
}
static void
#ifdef __STDC__
UNLOCKSCR(register struct screen *sc)
#else
UNLOCKSCR(sc)
register struct screen *sc;
#endif
{
sigset_t s, t;
sigfillset(&s);
sigprocmask(SIG_BLOCK, &s, &t);
sc->flags &= ~SM_LOCK;
j_psignal(&sc->flags, 0);
sigprocmask(SIG_SETMASK, &t, 0);
}
/*
* I/O routines come in two flavors. The internal ones, which start with
* "s", are used by rflush() and by the external ones. The external ones are
* used by the rest of NOS.
*/
static void
sputch(struct session *s, int c)
{
(*s->screen->sessmgr->putch)(s->screen->sessmgr, s->screen->sesmdat, c);
}
static void
scputs(struct session *s, char *str)
{
register struct screen *sp;
sp = s->screen;
while (*str)
(*sp->sessmgr->putch)(sp->sessmgr, sp->sesmdat, *str++);
}
static void
sclreol(struct session *s)
{
(*s->screen->sessmgr->clreol)(s->screen->sessmgr, s->screen->sesmdat);
}
/*
* rflush() used to flush data to the display process. Now it does I/O itself;
* the display process is defunct.
*/
void
rflush(void)
{
struct session *sp;
int i, c;
if (!Sessions || !sesm_initted)
return; /* timer could tick before we exist, or while suspended */
for (sp = Sessions, i = 0; i < Nsessions; sp++, i++)
{
if (sp->type == FREE)
continue;
if (!sp->screen || !sp->screen->sessmgr || !sp->screen->sesmdat)
continue;
if (!(sp->screen->flags & SMS_ACTIVE) || sp->morewait == 1)
continue;
/* err, do I want to do this? */
if (sp->screen->sessmgr->flags & SM_SUSPEND)
continue;
if (!LOCKSCR(sp->screen, 0))
{
write(2, "screen not responding - still trying\r\n", 38);
continue;
}
(*sp->screen->sessmgr->rflush)(sp->screen->sessmgr,
sp->screen->sesmdat);
if (sp->morewait == 2)
{
sp->morewait = 0;
sputch(sp, '\r');
sclreol(sp);
}
while (socklen(sp->output, 0) > 0)
{
if ((c = rrecvchar(sp->output)) == -1)
continue;
if (!sp->split || c != 0x0a)
sputch(sp, c);
else
{
scputs(sp, Eol);
sclreol(sp);
}
if (sp->record != NULLFILE)
{
if (c == '\r' || c == '\n')
fflush(sp->record);
if (c != '\r' || sockmode(sp->output, -1) != SOCK_ASCII)
putc(c, sp->record);
}
if (sp->flowmode && c == '\n' && sp->row > 0 && --sp->row == 0)
{
scputs(sp, "--More--");
sp->morewait = 1;
break;
}
}
(*sp->screen->sessmgr->flush)(sp->screen->sessmgr,
sp->screen->sesmdat);
UNLOCKSCR(sp->screen);
}
}
/*
* Public output routines. getcursess() attempts to intuit the correct session
* for output.
*/
static struct session *
getcursess(void)
{
static struct proc *kbproc;
/* this is a horrible hack that will (MUST!) go away in the future */
if (!kbproc && Curproc && strcmp(Curproc->name, "keyboard") == 0)
kbproc = Curproc;
if (kbproc == Curproc)
return Current;
/*
* if Curproc's session isn't active we must block...
* N.B. should handle trace with a special flag indicating that the
* session should discard output instead of blocking
*/
if (!(Curproc->session->screen->flags & SMS_ACTIVE))
{
#if 0
if (Curproc->session->screen->flags & SMS_DISCARD)
return 0;
#endif
pwait(Current->screen);
}
return Curproc->session;
}
void
putch(int c)
{
struct session *sp;
sp = getcursess();
LOCKSCR(sp->screen, 1);
sputch(sp, c);
UNLOCKSCR(sp->screen);
}
void
cputs(char *s)
{
struct session *sp;
sp = getcursess();
LOCKSCR(sp->screen, 1);
scputs(sp, s);
UNLOCKSCR(sp->screen);
}
void
clreol(void)
{
struct session *sp;
sp = getcursess();
LOCKSCR(sp->screen, 1);
sclreol(sp);
UNLOCKSCR(sp->screen);
}
void
clrscr(void)
{
register struct screen *sp;
sp = getcursess()->screen;
LOCKSCR(sp, 1);
(*sp->sessmgr->clrscr)(sp->sessmgr, sp->sesmdat);
UNLOCKSCR(sp);
}
int
wherex(void)
{
register struct screen *sp;
int i;
sp = getcursess()->screen;
if (sp->sessmgr->wherex)
{
LOCKSCR(sp, 1);
i = (*sp->sessmgr->wherex)(sp->sessmgr, sp->sesmdat);
UNLOCKSCR(sp);
return i;
}
return -1;
}
int
wherey(void)
{
register struct screen *sp;
int i;
sp = getcursess()->screen;
if (sp->sessmgr->wherey)
{
LOCKSCR(sp, 1);
i = (*sp->sessmgr->wherey)(sp->sessmgr, sp->sesmdat);
UNLOCKSCR(sp);
return i;
}
return -1;
}
void
window(int x1, int y1, int x2, int y2)
{
register struct screen *sp;
sp = getcursess()->screen;
if (sp->sessmgr->window)
{
LOCKSCR(sp, 1);
(*sp->sessmgr->window)(sp->sessmgr, sp->sesmdat, x1, y1, x2, y2);
UNLOCKSCR(sp);
}
}
void
gotoxy(int x, int y)
{
register struct screen *sp;
sp = getcursess()->screen;
LOCKSCR(sp, 1);
(*sp->sessmgr->gotoxy)(sp->sessmgr, sp->sesmdat, x, y);
UNLOCKSCR(sp);
}
void
highvideo(void)
{
register struct screen *sp;
sp = getcursess()->screen;
LOCKSCR(sp, 1);
(*sp->sessmgr->high)(sp->sessmgr, sp->sesmdat);
UNLOCKSCR(sp);
}
void
normvideo(void)
{
register struct screen *sp;
sp = getcursess()->screen;
LOCKSCR(sp, 1);
(*sp->sessmgr->norm)(sp->sessmgr, sp->sesmdat);
UNLOCKSCR(sp);
}
void
_setcursortype(int t)
{
register struct screen *sp;
sp = getcursess()->screen;
if (sp->sessmgr->cursor)
{
LOCKSCR(sp, 1);
(*sp->sessmgr->cursor)(sp->sessmgr, sp->sesmdat, t);
UNLOCKSCR(sp);
}
}
int
kbread(void)
{
register struct screen *sp;
sp = getcursess()->screen;
return (*sp->sessmgr->kbread)(sp->sessmgr, sp->sesmdat);
}
/*
* The status entry point is different: any routine may call the status output
* routine, which calls the status switch entry for the Command screen. If
* that is NULL, we perform direct output without passing information to
* rflush(); this avoids the flow control problems which have plagued previous
* versions, although it requires that we duplicate parts of rflush() here
* (and it's ugly).
*
* The numeric argument is presently ignored. Eventually I may use it for
* a positioning hint.
*/
void
sm_status(int pos, char *str)
{
struct screen *cs;
cs = Command->screen;
if (cs->sessmgr->status)
(*cs->sessmgr->status)(cs->sessmgr, cs->sesmdat, pos, str);
else
{
if (cs->sessmgr->flags & SM_SUSPEND)
return;
if (!(cs->flags & SMS_ACTIVE))
return;
LOCKSCR(cs, 1);
(*cs->sessmgr->rflush)(cs->sessmgr, cs->sesmdat);
/* should translate \n to Eol */
scputs(Command, str);
#if 0
scputs(Command, Eol);
#endif
(*cs->sessmgr->flush)(cs->sessmgr, cs->sesmdat);
UNLOCKSCR(cs);
}
}